不知不覺就寫了半個月了,每天下班的行程就是趕著寫文章。
在前一篇有提到 ConfigMap,是將非敏感性的資料以明文的方式儲存。這篇提到的 Secret 則是專門用來儲存敏感資訊,例如資料庫 host、帳號、密碼或 keys(例如:API key)。儲存在 sercret 時是以編碼的形式儲存,意思是 secret 只能儲存經編碼(base64)後的資料。
事實上在 secret 中僅是將資料編碼後儲存,並非加密後儲存。將專案上傳到公開的 repository 像是 GitHub 時切記勿把 secret 資料也上傳!因為他人拿到後一樣可以 decode(解碼) 回去。若是要確保 secret 的安全性,建議啟用靜態加密(Encryption at Rest),將 secret 中的敏感信息進行加密後再存儲到 etcd,例如建立一把 secret key 對 secret 的資料進行加密。
另外就是在相同的 namespace 下,任何 pod 或 deployment 皆可以直接存取到相同 namespace 下的 secret。
在 Linux 或 macOS 環境下編碼。
echo -n 'data' | base64
ZGF0YQ==
解碼(因指令和輸出會被紀錄下來,故不建議在實務中使用該命令)。
echo 'ZGF0YQ==' | base64 --decode
data%
在實務上建議以下方式查看。
kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode
建立 secret 的方式有幾種:
建立 test-secret.yaml
。
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
username: bXktYXBw # 注意這邊是經編碼後的資料
password: Mzk1MjgkdmRnN0pi # 注意這邊是經編碼後的資料
再執行指令。
kubectl creat -f test-secret.yaml
直接透過指令建立
例如直接在指令中填上 raw data。
kubectl create secret generic test-secret --from-literal='username=my-app' --from-literal='password=39528$vdg7Jb'
建立兩份檔案。
echo -n 'admin' > ./username.txt
echo -n 'S!B\*d$zDsb=' > ./password.txt
建立 secret。
kubectl create secret generic db-user-pass \
--from-file=username=./username.txt \
--from-file=password=./password.txt
pod 可藉由三種方式使用 secret:
envFrom
注入所有定義於 secret 的資料valueFrom
使用單個 secret 中的資料envFrom
建立 secret。
kubectl create secret generic test-secret --from-literal=username='my-app' --from-literal=password='39528$vdg7Jb'
secret/test-secret created
建立 pod-secret-envFrom.yaml
。
apiVersion: v1
kind: Pod
metadata:
name: envfrom-secret
spec:
containers:
- name: envars-test-container
image: nginx
envFrom: # 這邊會使用所有定義在 secret 中的 data
- secretRef:
name: test-secret
執行。
kubectl create -f pod-secret-envFrom.yaml
pod/envfrom-secret created
進入 pod 中查看變數。
kubectl exec -it envfrom-secret -- /bin/sh -c 'echo "username: $username\npassword: $password\n"'
username: my-app
password: 39528$vdg7Jb
valueFrom
注入建立 secret。
kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
secret/backend-user created
建立 pod-single-secret-env-variable.yaml
。
apiVersion: v1
kind: Pod
metadata:
name: env-single-secret
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: backend-user
key: backend-username # 將 backend-user 中的 backend-username 賦予給 SECRET_USERNAME 變數
執行。
kubectl create -f pod-single-secret-env-variable.yaml
pod/env-single-secret created
進入 pod 中查看變數。
kubectl exec -it env-single-secret -- /bin/sh -c 'echo $SECRET_USERNAME'
backend-admin
建立兩個 pods,一個使用 secret 中的生產環境變數,另一個用測試環境的環境變數。
建立生產環境。
kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret/prod-db-secret created
建立測試環境。
kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret/test-db-secret created
為避免變數中有特殊字元,若需要可使用單引號('
)來圍住資料。
建立 pod.yaml
,這邊會是以 volume 的形式使用 secret 資料。
cat <<EOF > pod.yaml
apiVersion: v1
kind: List
items:
- kind: Pod
apiVersion: v1
metadata:
name: prod-db-client-pod
labels:
name: prod-db-client
spec:
volumes:
- name: secret-volume
secret: # 這邊定義使用的 secret
secretName: prod-db-secret # 這邊定義 secret name
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume" # secret 的資料會儲存在容器中該路徑 /etc/secret-volume/ 下
- kind: Pod
apiVersion: v1
metadata:
name: test-db-client-pod
labels:
name: test-db-client
spec:
volumes:
- name: secret-volume
secret: # 這邊定義使用的 secret
secretName: test-db-secret # 這邊定義 secret name
containers:
- name: db-client-container
image: myClientImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume" # secret 的資料會儲存在容器中該路徑 /etc/secret-volume/ 下
EOF
建立 pods。
kubectl create -f pod.yaml
pod/prod-db-client-pod created
pod/test-db-client-pod created
實際使用
kubectl get pods
可能會看到 pods 的STATUS
為InvalidImageName
是正常的,因為文件上並沒有實際寫出這個 image 的來源,文件應僅是單純講解在 yaml 檔中要如何使用 secret。